#include "abbr_model.h"
#include "../../util.h"
#include "../config.h"

AbbrModel::AbbrModel(iostream *stop_words)
{
	string line;
	while(!stop_words->eof())
	{
		getline(*stop_words, line);
		stop.insert(line);
	}
}
bool AbbrModel::is_stop(string word)
{
	if(word.length() == 1)
		return true;
	return stop.find(word) != stop.end();
}

string AbbrModel::remove_stop(string str)
{
	string res;
	vector<string> &label_f = util::tokenize(str, " \t");
	for(int i = 0; i < label_f.size(); ++ i){
		if(!is_stop(label_f[i]) || i == 0 || i == label_f.size() - 1)
		{
			res += label_f[i];
			res += " ";
		}
	}
	return res;
}

bool AbbrModel::check_val(string sub, string base)
{
	if(sub.length() >= 4 && sub.length() >= base.length()/2)
		return false;
	int idx = 0;
	if(sub[0] != base[0])return false;
	for(int i = 1; i < sub.length(); ++ i){
		idx = base.find(sub[i], idx + 1);
		if(idx == -1 || idx > base.length() - 1)return false;
	}
	return true;
}

double AbbrModel::check_cover(int s_i, int s_j, vector<string> &total, string abbr)
{
	if(s_i == total.size() - 1)
	{
		if(check_val(abbr.substr(s_j, abbr.length() - s_j), total[s_i]))
			return 100;
		else
			return 0;
	}
	int start = s_j;
	if(total[s_i].find(abbr.substr(s_j, abbr.length() - s_j)) != -1)
		return 0;
	while(1){
		start = abbr.find(total[s_i + 1][0], start + 1);
		if(start == -1)break;
		if(!check_val(abbr.substr(s_j, start - s_j), total[s_i]))continue;
		else{
			double score = check_cover(s_i + 1, start, total, abbr);
			if(score != 0)
				return score;
		}
	}
	return 0;
}

double AbbrModel::trans_score(string sub, string base)
{
	vector<string> sub_t = util::tokenize(sub, " ");
	vector<string> base_t = util::tokenize(base, " ");
	string sub_f;
	for(int i = 0; i < sub_t.size(); ++ i)
		sub_f += sub_t[i];
	return check_cover(0, 0, base_t, sub_f);
}

void AbbrModel::build(map<string, int> &sourse, map<string, int> &model)
{
	map<string, int>::iterator q_i_itr, q_j_itr;
	for(q_i_itr = sourse.begin(); q_i_itr != sourse.end(); ++ q_i_itr)
		for(q_j_itr = sourse.begin(); q_j_itr != sourse.end(); ++ q_j_itr)
		{
			string q_i = (*q_i_itr).first;
			string q_j = (*q_j_itr).first;
			if(q_i == q_j) continue;
			string q_ij = util::minus(q_i, q_j);
			string q_ji = util::minus(q_j, q_i);
			string qs = util::short_str(q_ij, q_ji);
			string ql = util::long_str(q_ij, q_ji);
			double rate = (double)qs.length()/ql.length();
			if(qs.length() == 0 || rate > 0.4 || ql.find(" ") == ql.length() - 1)continue;
			if(q_ij == q_i && util::count_char(ql, " ") < 2)continue;
			double score = trans_score(qs, ql);
			if(score > atoi(Config::get("trans_thr").c_str()))
			{
				string code = ql + ">" + qs;
				map<string, int>::iterator l_itr = model.find(code);
				if(l_itr == model.end())
					model.insert(pair<string, int>(code, 1));
				else
					(*l_itr).second ++;
			}
		}
	for(q_i_itr = sourse.begin(); q_i_itr != sourse.end(); ++ q_i_itr)
		for(q_j_itr = sourse.begin(); q_j_itr != sourse.end(); ++ q_j_itr)
		{
			string q_i = (*q_i_itr).first;
			string q_j = (*q_j_itr).first;			
			if(q_i == q_j) continue;
			string q_ij = util::minus(q_i, q_j);
			string q_ji = util::minus(q_j, q_i);
			string ql = util::long_str(q_ij, q_ji);
			string ql1 = remove_stop(ql);
			if(ql == ql1) continue;
			string code_left = (ql == q_ij)? q_ij: q_ji;
			ql = ql1;
			string qs = util::short_str(q_ij, q_ji);
			string code_right = (qs == q_ij)? q_ij: q_ji;
			double rate = (double)qs.length()/ql.length();
			if(qs.length() == 0 || rate > 0.4 || ql.find(" ") == ql.length() - 1)continue;
			if(q_ij == q_i && util::count_char(ql, " ") < 2)continue;
			double score = trans_score(qs, ql);
			if(score > atoi(Config::get("trans_thr").c_str()))
			{
				string code = code_left + ">" + code_right;
				map<string, int>::iterator l_itr = model.find(code);
				if(l_itr == model.end())
					model.insert(pair<string, int>(code, 1));
				else
					(*l_itr).second ++;
			}
		}
}